home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 March / macformat-022.iso / Shareware City / Developers / src / out-of-phase-102-c / OutOfPhase 1.02 Source / OutOfPhase Folder / OscBankPlayer.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-23  |  33.3 KB  |  976 lines  |  [TEXT/KAHL]

  1. /* OscBankPlayer.c */
  2. /*****************************************************************************/
  3. /*                                                                           */
  4. /*    Out Of Phase:  Digital Music Synthesis on General Purpose Computers    */
  5. /*    Copyright (C) 1994  Thomas R. Lawrence                                 */
  6. /*                                                                           */
  7. /*    This program is free software; you can redistribute it and/or modify   */
  8. /*    it under the terms of the GNU General Public License as published by   */
  9. /*    the Free Software Foundation; either version 2 of the License, or      */
  10. /*    (at your option) any later version.                                    */
  11. /*                                                                           */
  12. /*    This program is distributed in the hope that it will be useful,        */
  13. /*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
  14. /*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
  15. /*    GNU General Public License for more details.                           */
  16. /*                                                                           */
  17. /*    You should have received a copy of the GNU General Public License      */
  18. /*    along with this program; if not, write to the Free Software            */
  19. /*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
  20. /*                                                                           */
  21. /*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
  22. /*                                                                           */
  23. /*****************************************************************************/
  24.  
  25. #include "MiscInfo.h"
  26. #include "Audit.h"
  27. #include "Debug.h"
  28. #include "Definitions.h"
  29.  
  30. #define ShowMeFrozenNoteRec
  31. #define ShowMe_NoteObjectRec
  32. #include "OscBankPlayer.h"
  33. #include "LFOGenerator.h"
  34. #include "IncrementalParameterUpdator.h"
  35. #include "LFOSpecifier.h"
  36. #include "LFOListSpecifier.h"
  37. #include "Memory.h"
  38. #include "Array.h"
  39. #include "OscillatorListSpecifier.h"
  40. #include "OscillatorSpecifier.h"
  41. #include "InstrumentStructure.h"
  42. #include "GenInstrTopology.h"
  43. #include "SampleOscControl.h"
  44. #include "WaveTableOscControl.h"
  45. #include "ModulationOscControl.h"
  46. #include "DeterminedNoteStructure.h"
  47. #include "NoteObject.h"
  48. #include "FloatingPoint.h"
  49. #include "Frequency.h"
  50. #include "ErrorDaemon.h"
  51.  
  52.  
  53. typedef struct
  54.     {
  55.         /* this is the reference to the template object */
  56.         void*                                        TemplateReference;
  57.  
  58.         /* perform one envelope update cycle */
  59.         void                                        (*UpdateEnvelopes)(void* State);
  60.         /* dispose of the state record */
  61.         void                                        (*DisposeState)(void* State);
  62.         /* dispose of the information template */
  63.         void                                        (*DisposeTemplate)(void* Template);
  64.         /* create a new state object. */
  65.         void*                                        (*NewState)(void* Template,
  66.                                                             float FreqForMultisampling, float Accent1, float Accent2,
  67.                                                             float Accent3, float Accent4, float Loudness, float HurryUp,
  68.                                                             long* PreOriginTimeOut, float StereoPosition,
  69.                                                             float InitialFrequency);
  70.         /* fix up pre-origin time for the state object */
  71.         void                                        (*FixUpStatePreOrigin)(void* State, long ActualPreOrigin);
  72.         /* set a new frequency for a state object.  used for portamento */
  73.         /* and modulation of frequency (vibrato) */
  74.         void                                        (*StateNewFrequency)(void* State, float NewFrequencyHertz);
  75.         /* send a key-up signal to one of the oscillators */
  76.         void                                        (*KeyUpSustain1)(void* State);
  77.         void                                        (*KeyUpSustain2)(void* State);
  78.         void                                        (*KeyUpSustain3)(void* State);
  79.         /* restart a oscillator.  this is used for tie continuations */
  80.         void                                        (*RestartState)(void* State, float NewFreqMultisampling,
  81.                                                             float NewAccent1, float NewAccent2, float NewAccent3,
  82.                                                             float NewAccent4, float NewLoudness, float NewHurryUp,
  83.                                                             MyBoolean RetriggerEnvelopes, float NewStereoPosition,
  84.                                                             float NewInitialFrequency);
  85.         /* generate a sequence of samples (called for each envelope clock) */
  86.         void                                        (*GenSamples)(void* State, long SampleCount,
  87.                                                             largefixedsigned* RawBuffer);
  88.         /* find out if the oscillator has finished yet */
  89.         MyBoolean                                (*IsItFinished)(void* State);
  90.     } OscBankVectorRec;
  91.  
  92.  
  93. struct OscBankTemplateRec
  94.     {
  95.         /* general parameters */
  96.         MyBoolean                                StereoOutput;
  97.         float                                        OverallVolumeScalingFactor;
  98.         long                                        SamplingRate;
  99.         float                                        EnvelopeUpdateRate;
  100.         MyBoolean                                TimeInterpolation;
  101.         MyBoolean                                WaveInterpolation;
  102.  
  103.         /* parameter updator for track (so we can set up individual notes properly) */
  104.         IncrParamUpdateRec*            ParamUpdator;
  105.  
  106.         /* template for the pitch displacement LFO */
  107.         LFOListSpecRec*                    PitchLFOTemplate;
  108.  
  109.         /* instrument overall loudness */
  110.         float                                        InstrOverallLoudness;
  111.  
  112.         /* list of template records describing each oscillator */
  113.         OscBankVectorRec*                TemplateArray;
  114.         /* this is the number of oscillators in the array */
  115.         long                                        NumOscillatorsInBank;
  116.     };
  117.  
  118.  
  119. typedef struct OscStateRec
  120.     {
  121.         /* this is a reference to the state object for this oscillator */
  122.         void*                                        StateReference;
  123.  
  124.         /* copy of the routine vectors */
  125.         OscBankVectorRec                Template;
  126.  
  127.         /* next oscillator in the list */
  128.         struct OscStateRec*            Next;
  129.     } OscStateRec;
  130.  
  131.  
  132. struct OscStateBankRec
  133.     {
  134.         /* what are we derived from */
  135.         OscBankTemplateRec*            BankTemplate;
  136.  
  137.         /* list of oscillators that this oscillator bank is comprised of */
  138.         OscStateRec*                        OscillatorList;
  139.  
  140.         /* this calculates the differential values for periodic pitch displacements */
  141.         LFOGenRec*                            PitchLFO;
  142.  
  143.         /* if this object ties to a note, then this is the note to tie to.  this is */
  144.         /* used for finding existing oscillators for tie continuations. */
  145.         struct NoteObjectRec*        TieToNote;
  146.  
  147.         /* portamento control parameters */
  148.         long                                        PortamentoCounter; /* 0 = done */
  149.         long                                        TotalPortamentoTicks;
  150.         float                                        InitialFrequency;
  151.         float                                        FinalFrequency;
  152.         float                                        CurrentFrequency;
  153.         /* True = portamento linear to Hertz; False = portamento linear to half-steps */
  154.         MyBoolean                                PortamentoHertz;
  155.         MyBoolean                                PitchLFOHertz;
  156.  
  157.         /* various counters (in terms of envelope ticks) */
  158.         /* negative = expired */
  159.         long                                        Release1Countdown;
  160.         long                                        Release2Countdown;
  161.         long                                        Release3Countdown;
  162.         long                                        PitchLFOStartCountdown;
  163.  
  164.         /* next oscillator bank in the list */
  165.         struct OscStateBankRec*    Next;
  166.     };
  167.  
  168.  
  169. static OscStateRec*                            StateFreeList = NIL;
  170. static OscStateBankRec*                    StateBankFreeList = NIL;
  171.  
  172.  
  173. /* flush all cached oscillator state bank records */
  174. void                                    FlushCachedOscStateBankRecords(void)
  175.     {
  176.         while (StateBankFreeList != NIL)
  177.             {
  178.                 OscStateBankRec*        Temp;
  179.  
  180.                 Temp = StateBankFreeList;
  181.                 StateBankFreeList = StateBankFreeList->Next;
  182.                 ReleasePtr((char*)Temp);
  183.             }
  184.  
  185.         while (StateFreeList != NIL)
  186.             {
  187.                 OscStateRec*                Temp;
  188.  
  189.                 Temp = StateFreeList;
  190.                 StateFreeList = StateFreeList->Next;
  191.                 ReleasePtr((char*)Temp);
  192.             }
  193.     }
  194.  
  195.  
  196. #if DEBUG
  197. static void                    ValidateOscState(OscStateRec* State)
  198.     {
  199.         OscStateRec*            Scan;
  200.  
  201.         CheckPtrExistence(State);
  202.         Scan = StateFreeList;
  203.         while (Scan != NIL)
  204.             {
  205.                 if (Scan == State)
  206.                     {
  207.                         PRERR(ForceAbort,"ValidateOscState:  state object is on free list");
  208.                     }
  209.                 Scan = Scan->Next;
  210.             }
  211.     }
  212. #else
  213. #define ValidateOscState(x) ((void)0)
  214. #endif
  215.  
  216.  
  217. #if DEBUG
  218. static void                    ValidateOscStateBank(OscStateBankRec* StateBank)
  219.     {
  220.         OscStateBankRec*    Scan;
  221.  
  222.         CheckPtrExistence(StateBank);
  223.         Scan = StateBankFreeList;
  224.         while (Scan != NIL)
  225.             {
  226.                 if (Scan == StateBank)
  227.                     {
  228.                         PRERR(ForceAbort,"ValidateOscStateBank:  state bank object is on free list");
  229.                     }
  230.                 Scan = Scan->Next;
  231.             }
  232.     }
  233. #else
  234. #define ValidateOscStateBank(x) ((void)0)
  235. #endif
  236.  
  237.  
  238. /* construct an oscillator bank template record.  various parameters are passed in */
  239. /* which are needed for synthesis.  ParameterUpdator is the parameter information */
  240. /* record for the whole track of which this is a part. */
  241. OscBankTemplateRec*        NewOscBankTemplate(struct InstrumentRec* InstrumentDefinition,
  242.                                                 MyBoolean StereoFlag, LargeBCDType OverallVolumeScalingReciprocal,
  243.                                                 long SamplingRate, float EnvelopeRate, MyBoolean TimeInterp,
  244.                                                 MyBoolean WaveInterp, struct IncrParamUpdateRec* ParameterUpdator,
  245.                                                 ErrorDaemonRec* ErrorDaemon)
  246.     {
  247.         OscBankTemplateRec*    Template;
  248.         ArrayRec*                        TwoDOscList;
  249.         OscillatorListRec*    OscillatorListObject;
  250.         OscillatorRec**            OscillatorVector;
  251.         long                                Scan;
  252.  
  253.         CheckPtrExistence(InstrumentDefinition);
  254.         CheckPtrExistence(ParameterUpdator);
  255.         CheckPtrExistence(ErrorDaemon);
  256.  
  257.         Template = (OscBankTemplateRec*)AllocPtrCanFail(sizeof(OscBankTemplateRec),
  258.             "OscBankTemplateRec");
  259.         if (Template == NIL)
  260.             {
  261.              FailurePoint1:
  262.                 return NIL;
  263.             }
  264.  
  265.         /* the oscillator bank template contains all of the information needed for */
  266.         /* constructing oscillators as notes are to be executed. */
  267.         /* number of oscillators in a bank. */
  268.         OscillatorListObject = GetInstrumentOscillatorList(InstrumentDefinition);
  269.         OscillatorVector = (OscillatorRec**)AllocPtrCanFail(sizeof(OscillatorRec*)
  270.             * GetOscillatorListLength(OscillatorListObject),"OscillatorRec[]");
  271.         if (OscillatorVector == NIL)
  272.             {
  273.              FailurePoint2:
  274.                 ReleasePtr((char*)Template);
  275.                 goto FailurePoint1;
  276.             }
  277.         for (Scan = 0; Scan < GetOscillatorListLength(OscillatorListObject); Scan += 1)
  278.             {
  279.                 PRNGCHK(OscillatorVector,&(OscillatorVector[Scan]),sizeof(OscillatorVector[Scan]));
  280.                 OscillatorVector[Scan] = GetOscillatorFromList(OscillatorListObject,Scan);
  281.             }
  282.         TwoDOscList = BuildOscillatorLists(OscillatorVector,
  283.             GetOscillatorListLength(OscillatorListObject));
  284.         if (TwoDOscList == NIL)
  285.             {
  286.              FailurePoint3:
  287.                 ReleasePtr((char*)OscillatorVector);
  288.                 goto FailurePoint2;
  289.             }
  290.  
  291.         /* get LFO information */
  292.         Template->PitchLFOTemplate = GetInstrumentFrequencyLFOList(InstrumentDefinition);
  293.  
  294.         /* vector containing templates for all of the oscillators */
  295.         Template->TemplateArray = (OscBankVectorRec*)AllocPtrCanFail(
  296.             sizeof(OscBankVectorRec) * ArrayGetLength(TwoDOscList),
  297.             "OscBankVectorRec");
  298.         if (Template->TemplateArray == NIL)
  299.             {
  300.              FailurePoint4:
  301.                 for (Scan = 0; Scan < ArrayGetLength(TwoDOscList); Scan += 1)
  302.                     {
  303.                         DisposeArray((ArrayRec*)ArrayGetElement(TwoDOscList,Scan));
  304.                     }
  305.                 DisposeArray(TwoDOscList);
  306.                 goto FailurePoint3;
  307.             }
  308.  
  309.         Template->NumOscillatorsInBank = 0;
  310.         for (Scan = 0; Scan < ArrayGetLength(TwoDOscList); Scan += 1)
  311.             {
  312.                 ArrayRec*                    OneOscArray;
  313.  
  314.                 OneOscArray = (ArrayRec*)ArrayGetElement(TwoDOscList,Scan);
  315.                 CheckPtrExistence(OneOscArray);
  316.                 if ((ArrayGetLength(OneOscArray) == 1) && (GetModulationSpecNumEntries(
  317.                     OscillatorGetModulatorInputList((OscillatorRec*)ArrayGetElement(
  318.                     OneOscArray,0))) == 0))
  319.                     {
  320.                         OscillatorRec*        Osc;
  321.  
  322.                         Osc = (OscillatorRec*)ArrayGetElement(OneOscArray,0);
  323.                         CheckPtrExistence(Osc);
  324.                         switch (OscillatorGetWhatKindItIs(Osc))
  325.                             {
  326.                                 default:
  327.                                     EXECUTE(PRERR(ForceAbort,"NewOscBankTemplate:  bad oscillator type"));
  328.                                     break;
  329.                                 case eOscillatorSampled:
  330.                                     PRNGCHK(Template->TemplateArray,&(Template->TemplateArray[Scan]),
  331.                                         sizeof(Template->TemplateArray[Scan]));
  332.                                     Template->TemplateArray[Scan].TemplateReference
  333.                                         = NewSampleTemplate(Osc,EnvelopeRate,SamplingRate,StereoFlag,
  334.                                         TimeInterp,WaveInterp,ErrorDaemon);
  335.                                     if (Template->TemplateArray[Scan].TemplateReference == NIL)
  336.                                         {
  337.                                          FailurePoint5:
  338.                                             for (Scan = 0; Scan < Template->NumOscillatorsInBank; Scan += 1)
  339.                                                 {
  340.                                                     (*Template->TemplateArray[Scan]
  341.                                                         .DisposeTemplate)(Template->TemplateArray[
  342.                                                         Scan].TemplateReference);
  343.                                                 }
  344.                                             goto FailurePoint4;
  345.                                         }
  346.                                     Template->TemplateArray[Scan].UpdateEnvelopes
  347.                                         = (void (*)(void*))&UpdateSampleEnvelopes;
  348.                                     Template->TemplateArray[Scan].DisposeState
  349.                                         = (void (*)(void*))&DisposeSampleState;
  350.                                     Template->TemplateArray[Scan].DisposeTemplate
  351.                                         = (void (*)(void*))&DisposeSampleTemplate;
  352.                                     Template->TemplateArray[Scan].NewState
  353.                                         = (void* (*)(void*,float,float,float,float,float,
  354.                                         float,float,long*,float,float))&NewSampleState;
  355.                                     Template->TemplateArray[Scan].FixUpStatePreOrigin
  356.                                         = (void (*)(void*,long))&FixUpSampleStatePreOrigin;
  357.                                     Template->TemplateArray[Scan].StateNewFrequency
  358.                                         = (void (*)(void*,float))&SampleStateNewFrequency;
  359.                                     Template->TemplateArray[Scan].KeyUpSustain1
  360.                                         = (void (*)(void*))&SampleKeyUpSustain1;
  361.                                     Template->TemplateArray[Scan].KeyUpSustain2
  362.                                         = (void (*)(void*))&SampleKeyUpSustain2;
  363.                                     Template->TemplateArray[Scan].KeyUpSustain3
  364.                                         = (void (*)(void*))&SampleKeyUpSustain3;
  365.                                     Template->TemplateArray[Scan].RestartState
  366.                                         = (void (*)(void*,float,float,float,float,float,float,float,
  367.                                         MyBoolean,float,float))&RestartSampleState;
  368.                                     Template->TemplateArray[Scan].GenSamples
  369.                                         = (void (*)(void*,long,largefixedsigned*))&SampleGenSamples;
  370.                                     Template->TemplateArray[Scan].IsItFinished
  371.                                         = (MyBoolean (*)(void*))&SampleIsItFinished;
  372.                                     break;
  373.                                 case eOscillatorWaveTable:
  374.                                     PRNGCHK(Template->TemplateArray,&(Template->TemplateArray[Scan]),
  375.                                         sizeof(Template->TemplateArray[Scan]));
  376.                                     Template->TemplateArray[Scan].TemplateReference
  377.                                         = NewWaveTableTemplate(Osc,EnvelopeRate,SamplingRate,StereoFlag,
  378.                                         TimeInterp,WaveInterp,ErrorDaemon);
  379.                                     if (Template->TemplateArray[Scan].TemplateReference == NIL)
  380.                                         {
  381.                                             goto FailurePoint5;
  382.                                         }
  383.                                     Template->TemplateArray[Scan].UpdateEnvelopes
  384.                                         = (void (*)(void*))&UpdateWaveTableEnvelopes;
  385.                                     Template->TemplateArray[Scan].DisposeState
  386.                                         = (void (*)(void*))&DisposeWaveTableState;
  387.                                     Template->TemplateArray[Scan].DisposeTemplate
  388.                                         = (void (*)(void*))&DisposeWaveTableTemplate;
  389.                                     Template->TemplateArray[Scan].NewState
  390.                                         = (void* (*)(void*,float,float,float,float,float,
  391.                                         float,float,long*,float,float))&NewWaveTableState;
  392.                                     Template->TemplateArray[Scan].FixUpStatePreOrigin
  393.                                         = (void (*)(void*,long))&FixUpWaveTableStatePreOrigin;
  394.                                     Template->TemplateArray[Scan].StateNewFrequency
  395.                                         = (void (*)(void*,float))&WaveTableStateNewFrequency;
  396.                                     Template->TemplateArray[Scan].KeyUpSustain1
  397.                                         = (void (*)(void*))&WaveTableKeyUpSustain1;
  398.                                     Template->TemplateArray[Scan].KeyUpSustain2
  399.                                         = (void (*)(void*))&WaveTableKeyUpSustain2;
  400.                                     Template->TemplateArray[Scan].KeyUpSustain3
  401.                                         = (void (*)(void*))&WaveTableKeyUpSustain3;
  402.                                     Template->TemplateArray[Scan].RestartState
  403.                                         = (void (*)(void*,float,float,float,float,float,float,float,
  404.                                         MyBoolean,float,float))&RestartWaveTableState;
  405.                                     Template->TemplateArray[Scan].GenSamples
  406.                                         = (void (*)(void*,long,largefixedsigned*))&WaveTableGenSamples;
  407.                                     Template->TemplateArray[Scan].IsItFinished
  408.                                         = (MyBoolean (*)(void*))&WaveTableIsItFinished;
  409.                                     break;
  410.                             }
  411.                     }
  412.                  else
  413.                     {
  414.                         PRNGCHK(Template->TemplateArray,&(Template->TemplateArray[Scan]),
  415.                             sizeof(Template->TemplateArray[Scan]));
  416.                         Template->TemplateArray[Scan].TemplateReference
  417.                             = NewModOscTemplate(OneOscArray,EnvelopeRate,SamplingRate,StereoFlag,
  418.                             TimeInterp,WaveInterp,ErrorDaemon);
  419.                         if (Template->TemplateArray[Scan].TemplateReference == NIL)
  420.                             {
  421.                                 goto FailurePoint5;
  422.                             }
  423.                         Template->TemplateArray[Scan].UpdateEnvelopes
  424.                             = (void (*)(void*))&UpdateModOscEnvelopes;
  425.                         Template->TemplateArray[Scan].DisposeState
  426.                             = (void (*)(void*))&DisposeModOscState;
  427.                         Template->TemplateArray[Scan].DisposeTemplate
  428.                             = (void (*)(void*))&DisposeModOscTemplate;
  429.                         Template->TemplateArray[Scan].NewState
  430.                             = (void* (*)(void*,float,float,float,float,float,
  431.                             float,float,long*,float,float))&NewModOscState;
  432.                         Template->TemplateArray[Scan].FixUpStatePreOrigin
  433.                             = (void (*)(void*,long))&FixUpModOscStatePreOrigin;
  434.                         Template->TemplateArray[Scan].StateNewFrequency
  435.                             = (void (*)(void*,float))&ModOscStateNewFrequency;
  436.                         Template->TemplateArray[Scan].KeyUpSustain1
  437.                             = (void (*)(void*))&ModOscKeyUpSustain1;
  438.                         Template->TemplateArray[Scan].KeyUpSustain2
  439.                             = (void (*)(void*))&ModOscKeyUpSustain2;
  440.                         Template->TemplateArray[Scan].KeyUpSustain3
  441.                             = (void (*)(void*))&ModOscKeyUpSustain3;
  442.                         Template->TemplateArray[Scan].RestartState
  443.                             = (void (*)(void*,float,float,float,float,float,float,float,
  444.                             MyBoolean,float,float))&RestartModOscState;
  445.                         Template->TemplateArray[Scan].GenSamples
  446.                             = (void (*)(void*,long,largefixedsigned*))&ModOscGenSamples;
  447.                         Template->TemplateArray[Scan].IsItFinished
  448.                             = (MyBoolean (*)(void*))&ModOscIsItFinished;
  449.                     }
  450.                 Template->NumOscillatorsInBank += 1;
  451.             }
  452.  
  453.         /* playback control parameters */
  454.         Template->StereoOutput = StereoFlag;
  455.         Template->OverallVolumeScalingFactor = 1.0 / LargeBCD2Single(OverallVolumeScalingReciprocal);
  456.         Template->SamplingRate = SamplingRate;
  457.         Template->EnvelopeUpdateRate = EnvelopeRate;
  458.         Template->TimeInterpolation = TimeInterp;
  459.         Template->WaveInterpolation = WaveInterp;
  460.  
  461.         Template->ParamUpdator = ParameterUpdator;
  462.  
  463.         Template->InstrOverallLoudness = GetInstrumentOverallLoudness(InstrumentDefinition);
  464.  
  465.         /* clean up the mess */
  466.         for (Scan = 0; Scan < ArrayGetLength(TwoDOscList); Scan += 1)
  467.             {
  468.                 DisposeArray((ArrayRec*)ArrayGetElement(TwoDOscList,Scan));
  469.             }
  470.         DisposeArray(TwoDOscList);
  471.         ReleasePtr((char*)OscillatorVector);
  472.  
  473.         return Template;
  474.     }
  475.  
  476.  
  477. /* dispose of the template */
  478. void                                    DisposeOscBankTemplate(OscBankTemplateRec* Template)
  479.     {
  480.         long                                Scan;
  481.  
  482.         CheckPtrExistence(Template);
  483.  
  484.         for (Scan = 0; Scan < Template->NumOscillatorsInBank; Scan += 1)
  485.             {
  486.                 PRNGCHK(Template->TemplateArray,&(Template->TemplateArray[Scan]),
  487.                     sizeof(Template->TemplateArray[Scan]));
  488.                 (*Template->TemplateArray[Scan].DisposeTemplate)(Template->
  489.                     TemplateArray[Scan].TemplateReference);
  490.             }
  491.         ReleasePtr((char*)Template->TemplateArray);
  492.  
  493.         ReleasePtr((char*)Template);
  494.     }
  495.  
  496.  
  497. /* construct a new oscillator bank state object based on the note.  the note is */
  498. /* assumed to start "now" in terms of the parameters in the ParameterUpdator.  */
  499. /* the ScanningGapWidth is the number of envelope clock ticks in the current scanning */
  500. /* gap.  this is used to determine how far later than "now" in terms of the back */
  501. /* edge of the scanning gap (different from above) the osc bank should start playing. */
  502. /* *WhenToStartPlayingOut returns the number of envelope ticks after the back edge */
  503. /* of the scanning gap that the note should be started. */
  504. /*     <already played>       |    <scanning gap>     |    <not yet analyzed> */
  505. /*   time ---->    time ---->    time ---->    time ---->    time ---->   time ----> */
  506. /*                            ^A                      ^B     */
  507. /* point A is the back edge of the scanning gap.  as this edge moves forward in time, */
  508. /*   oscillator bank state objects are removed from the queue and playback is commenced */
  509. /*   for them. */
  510. /* point B is the front edge of the scanning gap.  as this edge moves forward in time, */
  511. /*   notes are extracted from the track and state bank objects are created for them. */
  512. /*   ParameterUpdator always reflects parameters at this point in time. */
  513. OscStateBankRec*            NewOscBankState(OscBankTemplateRec* Template,
  514.                                                 long* WhenToStartPlayingOut, struct NoteObjectRec* Note,
  515.                                                 float EnvelopeTicksPerDurationTick)
  516.     {
  517.         OscStateBankRec*        State;
  518.         long                                Scan;
  519.         FrozenNoteRec*            FrozenNote;
  520.         long                                StartPointAdjust;
  521.         long                                MaxOscillatorPreOriginTime;
  522.         OscStateRec*                OneState;
  523.         long                                ThisPreOriginTime;
  524.  
  525.         CheckPtrExistence(Template);
  526.         CheckPtrExistence(Note);
  527.  
  528.         if (StateBankFreeList != NIL)
  529.             {
  530.                 State = StateBankFreeList;
  531.                 StateBankFreeList = StateBankFreeList->Next;
  532.             }
  533.          else
  534.             {
  535.                 State = (OscStateBankRec*)AllocPtrCanFail(sizeof(OscStateBankRec),"OscStateBankRec");
  536.                 if (State == NIL)
  537.                     {
  538.                      FailurePoint1:
  539.                         return NIL;
  540.                     }
  541.             }
  542.         EXECUTE(State->Next = (OscStateBankRec*)0x81818181;)
  543.  
  544.         State->BankTemplate = Template;
  545.  
  546.         /* freeze the parameters */
  547.         FrozenNote = FixNoteParameters(Template->ParamUpdator,Note,&StartPointAdjust,
  548.             Template->OverallVolumeScalingFactor,EnvelopeTicksPerDurationTick);
  549.         if (FrozenNote == NIL)
  550.             {
  551.              FailurePoint2:
  552.                 State->Next = StateBankFreeList;
  553.                 StateBankFreeList = State;
  554.                 goto FailurePoint1;
  555.             }
  556.  
  557.         /* list of oscillators that this oscillator bank is comprised of */
  558.         State->OscillatorList = NIL;
  559.         MaxOscillatorPreOriginTime = 0;
  560.         for (Scan = 0; Scan < Template->NumOscillatorsInBank; Scan += 1)
  561.             {
  562.                 /* allocate the new record */
  563.                 if (StateFreeList != NIL)
  564.                     {
  565.                         OneState = StateFreeList;
  566.                         StateFreeList = StateFreeList->Next;
  567.                     }
  568.                  else
  569.                     {
  570.                         OneState = (OscStateRec*)AllocPtrCanFail(sizeof(OscStateRec),"OscStateRec");
  571.                         if (OneState == NIL)
  572.                             {
  573.                              FailurePoint3:
  574.                                 while (State->OscillatorList != NIL)
  575.                                     {
  576.                                         /* delink object */
  577.                                         OneState = State->OscillatorList;
  578.                                         State->OscillatorList = State->OscillatorList->Next;
  579.                                         /* dispose members */
  580.                                         (*OneState->Template.DisposeState)(OneState->StateReference);
  581.                                         /* stick on free list */
  582.                                         OneState->Next = StateFreeList;
  583.                                         StateFreeList = OneState;
  584.                                     }
  585.                                 goto FailurePoint2;
  586.                             }
  587.                     }
  588.  
  589.                 /* copy over the function vectors */
  590.                 PRNGCHK(Template->TemplateArray,&(Template->TemplateArray[Scan]),
  591.                     sizeof(Template->TemplateArray[Scan]));
  592.                 OneState->Template = Template->TemplateArray[Scan];
  593.  
  594.                 /* create the oscillator */
  595.                 OneState->StateReference = (OneState->Template.NewState)(
  596.                     OneState->Template.TemplateReference,FrozenNote->MultisampleFrequency,
  597.                     FrozenNote->Accent1,FrozenNote->Accent2,FrozenNote->Accent3,FrozenNote->Accent4,
  598.                     FrozenNote->LoudnessAdjust * Template->InstrOverallLoudness,
  599.                     FrozenNote->HurryUpFactor,&ThisPreOriginTime,FrozenNote->StereoPosition,
  600.                     FrozenNote->NominalFrequency);
  601.                 if (OneState->StateReference == NIL)
  602.                     {
  603.                      FailurePoint3a:
  604.                         OneState->Next = StateFreeList;
  605.                         StateFreeList = OneState;
  606.                         goto FailurePoint3;
  607.                     }
  608.  
  609.                 if (ThisPreOriginTime > MaxOscillatorPreOriginTime)
  610.                     {
  611.                         MaxOscillatorPreOriginTime = ThisPreOriginTime;
  612.                     }
  613.  
  614.                 /* link it in */
  615.                 OneState->Next = State->OscillatorList;
  616.                 State->OscillatorList = OneState;
  617.             }
  618.  
  619.         /* this calculates the differential values for periodic pitch displacements */
  620.         State->PitchLFOHertz = FrozenNote->PitchDisplacementDepthInHertz;
  621.         if (!State->PitchLFOHertz)
  622.             {
  623.                 /* half steps */
  624.                 State->PitchLFO = NewLFOGenerator(Template->PitchLFOTemplate,&ThisPreOriginTime,
  625.                     FrozenNote->Accent1,FrozenNote->Accent2,FrozenNote->Accent3,FrozenNote->Accent4,
  626.                     FrozenNote->NominalFrequency,FrozenNote->HurryUpFactor,
  627.                     Template->EnvelopeUpdateRate,FrozenNote->PitchDisplacementDepthLimit / 12,
  628.                     FrozenNote->PitchDisplacementRateLimit,eLFOArithGeometric,
  629.                     FrozenNote->MultisampleFrequency);
  630.             }
  631.          else
  632.             {
  633.                 State->PitchLFO = NewLFOGenerator(Template->PitchLFOTemplate,&ThisPreOriginTime,
  634.                     FrozenNote->Accent1,FrozenNote->Accent2,FrozenNote->Accent3,FrozenNote->Accent4,
  635.                     FrozenNote->NominalFrequency,FrozenNote->HurryUpFactor,
  636.                     Template->EnvelopeUpdateRate,FrozenNote->PitchDisplacementDepthLimit,
  637.                     FrozenNote->PitchDisplacementRateLimit,eLFOArithAdditive,
  638.                     FrozenNote->MultisampleFrequency);
  639.             }
  640.         if (State->PitchLFO == NIL)
  641.             {
  642.              FailurePoint4:
  643.                 goto FailurePoint3;
  644.             }
  645.         if (ThisPreOriginTime > MaxOscillatorPreOriginTime)
  646.             {
  647.                 MaxOscillatorPreOriginTime = ThisPreOriginTime;
  648.             }
  649.  
  650.         /* if this object ties to a note, then this is the note to tie to.  this is */
  651.         /* used for finding existing oscillators for tie continuations. */
  652.         State->TieToNote = Note->a.Note.Tie;
  653.  
  654.         /* portamento control parameters */
  655.         State->PortamentoCounter = 0;
  656.         State->CurrentFrequency = FrozenNote->NominalFrequency;
  657.  
  658.         /* fix up pre-origin times */
  659.         OneState = State->OscillatorList;
  660.         while (OneState != NIL)
  661.             {
  662.                 (*OneState->Template.FixUpStatePreOrigin)(OneState->StateReference,
  663.                     MaxOscillatorPreOriginTime);
  664.                 OneState = OneState->Next;
  665.             }
  666.         LFOGeneratorFixEnvelopeOrigins(State->PitchLFO,MaxOscillatorPreOriginTime);
  667.  
  668.         /* various counters (in terms of envelope ticks) */
  669.         if (State->TieToNote == NIL)
  670.             {
  671.                 State->Release1Countdown = FrozenNote->ReleasePoint1
  672.                     + MaxOscillatorPreOriginTime;
  673.                 State->Release2Countdown = FrozenNote->ReleasePoint2
  674.                     + MaxOscillatorPreOriginTime;
  675.                 State->Release3Countdown = FrozenNote->ReleasePoint3
  676.                     + MaxOscillatorPreOriginTime;
  677.             }
  678.          else
  679.             {
  680.                 /* for ties, only honor releases from start */
  681.                 if (FrozenNote->Release1FromStart)
  682.                     {
  683.                         State->Release1Countdown = FrozenNote->ReleasePoint1
  684.                             + MaxOscillatorPreOriginTime;
  685.                     }
  686.                  else
  687.                     {
  688.                         State->Release1Countdown = -1;
  689.                     }
  690.                 if (FrozenNote->Release2FromStart)
  691.                     {
  692.                         State->Release2Countdown = FrozenNote->ReleasePoint2
  693.                             + MaxOscillatorPreOriginTime;
  694.                     }
  695.                  else
  696.                     {
  697.                         State->Release2Countdown = -1;
  698.                     }
  699.                 if (FrozenNote->Release3FromStart)
  700.                     {
  701.                         State->Release3Countdown = FrozenNote->ReleasePoint3
  702.                             + MaxOscillatorPreOriginTime;
  703.                     }
  704.                  else
  705.                     {
  706.                         State->Release3Countdown = -1;
  707.                     }
  708.             }
  709.         State->PitchLFOStartCountdown = FrozenNote->PitchDisplacementStartPoint
  710.             + MaxOscillatorPreOriginTime;
  711.  
  712.         /* clean up */
  713.         DisposeFrozenNote(FrozenNote);
  714.  
  715.         *WhenToStartPlayingOut = StartPointAdjust - MaxOscillatorPreOriginTime;
  716.  
  717.         return State;
  718.     }
  719.  
  720.  
  721. /* this is used for resetting a note for a tie */
  722. /* the FrozenNote object is NOT disposed */
  723. MyBoolean                            ResetOscBankState(OscStateBankRec* State,
  724.                                                 struct FrozenNoteRec* FrozenNote,
  725.                                                 float EnvelopeTicksPerDurationTick)
  726.     {
  727.         OscStateRec*                OneState;
  728.         MyBoolean                        RetriggerEnvelopes;
  729.  
  730.         CheckPtrExistence(State);
  731.         ValidateOscStateBank(State);
  732.         CheckPtrExistence(FrozenNote);
  733.  
  734.         RetriggerEnvelopes = ((FrozenNote->OriginalNote->Flags
  735.             & eRetriggerEnvelopesOnTieFlag) != 0);
  736.  
  737.         /* go through the oscillators and retrigger them */
  738.         OneState = State->OscillatorList;
  739.         while (OneState != NIL)
  740.             {
  741.                 (*OneState->Template.RestartState)(OneState->StateReference,
  742.                     FrozenNote->MultisampleFrequency,FrozenNote->Accent1,FrozenNote->Accent2,
  743.                     FrozenNote->Accent3,FrozenNote->Accent4,FrozenNote->LoudnessAdjust
  744.                     * State->BankTemplate->InstrOverallLoudness,FrozenNote->HurryUpFactor,
  745.                     RetriggerEnvelopes,FrozenNote->StereoPosition,
  746.                     FrozenNote->NominalFrequency);
  747.                 OneState = OneState->Next;
  748.             }
  749.  
  750.         State->PitchLFOHertz = FrozenNote->PitchDisplacementDepthInHertz;
  751.         LFOGeneratorRetriggerFromOrigin(State->PitchLFO,FrozenNote->Accent1,
  752.             FrozenNote->Accent2,FrozenNote->Accent3,FrozenNote->Accent4,
  753.             FrozenNote->NominalFrequency,FrozenNote->HurryUpFactor,
  754.             State->BankTemplate->EnvelopeUpdateRate,
  755.             FrozenNote->PitchDisplacementDepthLimit
  756.             / (State->PitchLFOHertz ? 1 : 12), /* div by 12 only if half-steps */
  757.             FrozenNote->PitchDisplacementRateLimit,RetriggerEnvelopes);
  758.  
  759.         /* if this object ties to a note, then this is the note to tie to.  this is */
  760.         /* used for finding existing oscillators for tie continuations. */
  761.         State->TieToNote = FrozenNote->OriginalNote->a.Note.Tie;
  762.  
  763.         /* portamento control parameters */
  764.         if (FrozenNote->PortamentoDuration > 0)
  765.             {
  766.                 State->PortamentoCounter = FrozenNote->PortamentoDuration;
  767.                 State->TotalPortamentoTicks = FrozenNote->PortamentoDuration;
  768.                 State->InitialFrequency = State->CurrentFrequency; /* save current pitch */
  769.                 State->FinalFrequency = FrozenNote->NominalFrequency;
  770.                 State->PortamentoHertz = ((FrozenNote->OriginalNote->Flags
  771.                     & ePortamentoHertzNotHalfsteps) != 0);
  772.             }
  773.          else
  774.             {
  775.                 State->PortamentoCounter = 0;
  776.                 State->CurrentFrequency = FrozenNote->NominalFrequency;
  777.             }
  778.  
  779.         /* various counters (in terms of envelope ticks) */
  780.         if (State->TieToNote == NIL)
  781.             {
  782.                 State->Release1Countdown = FrozenNote->ReleasePoint1;
  783.                 State->Release2Countdown = FrozenNote->ReleasePoint2;
  784.                 State->Release3Countdown = FrozenNote->ReleasePoint3;
  785.             }
  786.          else
  787.             {
  788.                 /* for ties, only honor releases from start */
  789.                 if (FrozenNote->Release1FromStart)
  790.                     {
  791.                         State->Release1Countdown = FrozenNote->ReleasePoint1;
  792.                     }
  793.                  else
  794.                     {
  795.                         State->Release1Countdown = -1;
  796.                     }
  797.                 if (FrozenNote->Release2FromStart)
  798.                     {
  799.                         State->Release2Countdown = FrozenNote->ReleasePoint2;
  800.                     }
  801.                  else
  802.                     {
  803.                         State->Release2Countdown = -1;
  804.                     }
  805.                 if (FrozenNote->Release3FromStart)
  806.                     {
  807.                         State->Release3Countdown = FrozenNote->ReleasePoint3;
  808.                     }
  809.                  else
  810.                     {
  811.                         State->Release3Countdown = -1;
  812.                     }
  813.             }
  814.         if (RetriggerEnvelopes)
  815.             {
  816.                 State->PitchLFOStartCountdown = FrozenNote->PitchDisplacementStartPoint;
  817.             }
  818.          else
  819.             {
  820.                 State->PitchLFOStartCountdown = -1;
  821.             }
  822.  
  823.         return True;
  824.     }
  825.  
  826.  
  827. /* get rid of a state bank */
  828. void                                    DisposeOscStateBank(OscStateBankRec* State)
  829.     {
  830.         OscStateRec*                OneStateScan;
  831.  
  832.         CheckPtrExistence(State);
  833.         ValidateOscStateBank(State);
  834.  
  835.         OneStateScan = State->OscillatorList;
  836.         while (OneStateScan != NIL)
  837.             {
  838.                 OscStateRec*                Temp;
  839.  
  840.                 (*OneStateScan->Template.DisposeState)(OneStateScan->StateReference);
  841.                 Temp = OneStateScan;
  842.                 OneStateScan = OneStateScan->Next;
  843.                 Temp->Next = StateFreeList;
  844.                 StateFreeList = Temp;
  845.             }
  846.  
  847.         DisposeLFOGenerator(State->PitchLFO);
  848.  
  849.         State->Next = StateBankFreeList;
  850.         StateBankFreeList = State;
  851.     }
  852.  
  853.  
  854. /* get the reference to the note that this bank ties to.  NIL if it doesn't */
  855. struct NoteObjectRec*    GetOscStateTieTarget(OscStateBankRec* State)
  856.     {
  857.         CheckPtrExistence(State);
  858.         ValidateOscStateBank(State);
  859.  
  860.         return State->TieToNote;
  861.     }
  862.  
  863.  
  864. /* perform one envelope clock cycle on a state bank.  this returns True if the */
  865. /* state bank is done and should be retired.  (it will return false if it is a */
  866. /* tie source.) */
  867. MyBoolean                            UpdateOscStateBank(OscStateBankRec* State, long NumFrames,
  868.                                                 largefixedsigned* OutputData)
  869.     {
  870.         OscStateRec*                OneStateScan;
  871.         MyBoolean                        OscillatorsRunning;
  872.         float                                Frequency;
  873.  
  874.         CheckPtrExistence(State);
  875.         ValidateOscStateBank(State);
  876.  
  877.         if (State->Release1Countdown >= 0)
  878.             {
  879.                 if (State->Release1Countdown == 0)
  880.                     {
  881.                         OneStateScan = State->OscillatorList;
  882.                         while (OneStateScan != NIL)
  883.                             {
  884.                                 (*OneStateScan->Template.KeyUpSustain1)(OneStateScan->StateReference);
  885.                                 OneStateScan = OneStateScan->Next;
  886.                             }
  887.                         LFOGeneratorKeyUpSustain1(State->PitchLFO);
  888.                     }
  889.                 State->Release1Countdown -= 1;
  890.             }
  891.  
  892.         if (State->Release2Countdown >= 0)
  893.             {
  894.                 if (State->Release2Countdown == 0)
  895.                     {
  896.                         OneStateScan = State->OscillatorList;
  897.                         while (OneStateScan != NIL)
  898.                             {
  899.                                 (*OneStateScan->Template.KeyUpSustain2)(OneStateScan->StateReference);
  900.                                 OneStateScan = OneStateScan->Next;
  901.                             }
  902.                         LFOGeneratorKeyUpSustain2(State->PitchLFO);
  903.                     }
  904.                 State->Release2Countdown -= 1;
  905.             }
  906.  
  907.         if (State->Release3Countdown >= 0)
  908.             {
  909.                 if (State->Release3Countdown == 0)
  910.                     {
  911.                         OneStateScan = State->OscillatorList;
  912.                         while (OneStateScan != NIL)
  913.                             {
  914.                                 (*OneStateScan->Template.KeyUpSustain3)(OneStateScan->StateReference);
  915.                                 OneStateScan = OneStateScan->Next;
  916.                             }
  917.                         LFOGeneratorKeyUpSustain3(State->PitchLFO);
  918.                     }
  919.                 State->Release3Countdown -= 1;
  920.             }
  921.  
  922.         /* perform portamento */
  923.         if (State->PortamentoCounter > 0)
  924.             {
  925.                 /* decrement is done before interpolation so that the final frequency */
  926.                 /* will actually be reached. */
  927.                 State->PortamentoCounter -= 1;
  928.                 if (State->PortamentoHertz)
  929.                     {
  930.                         /* this transition is linear, so it's easy to compute */
  931.                         /* L+F(R-L) */
  932.                         State->CurrentFrequency = State->InitialFrequency
  933.                             + ((float)(State->TotalPortamentoTicks
  934.                             - State->PortamentoCounter) / State->TotalPortamentoTicks)
  935.                             * (State->FinalFrequency - State->InitialFrequency);
  936.                     }
  937.                  else
  938.                     {
  939.                         /* this transition is log-linear, so it's a bit messier */
  940.                         State->CurrentFrequency = State->InitialFrequency * (float)FEXP(
  941.                             ((float)(State->TotalPortamentoTicks - State->PortamentoCounter)
  942.                             / State->TotalPortamentoTicks)
  943.                             * (((float)FLN(State->FinalFrequency) / (float)LOG2)
  944.                             - ((float)FLN(State->InitialFrequency) / (float)LOG2)) * LOG2);
  945.                     }
  946.             }
  947.  
  948.         /* update the pitch LFO modulation & figure out what the current pitch is */
  949.         if (State->PitchLFOStartCountdown > 0)
  950.             {
  951.                 State->PitchLFOStartCountdown -= 1;
  952.                 Frequency = State->CurrentFrequency;
  953.             }
  954.          else
  955.             {
  956.                 /* do some pitch stuff */
  957.                 Frequency = FastFixed2Float(LFOGenUpdateCycle(State->PitchLFO,
  958.                     Double2FastFixed(State->CurrentFrequency)));
  959.             }
  960.  
  961.         /* perform a cycle of resampling */
  962.         OscillatorsRunning = False;
  963.         OneStateScan = State->OscillatorList;
  964.         while (OneStateScan != NIL)
  965.             {
  966.                 (*OneStateScan->Template.StateNewFrequency)(OneStateScan->StateReference,Frequency);
  967.                 (*OneStateScan->Template.UpdateEnvelopes)(OneStateScan->StateReference);
  968.                 (*OneStateScan->Template.GenSamples)(OneStateScan->StateReference,NumFrames,OutputData);
  969.                 OscillatorsRunning = OscillatorsRunning || !(*OneStateScan->Template
  970.                     .IsItFinished)(OneStateScan->StateReference);
  971.                 OneStateScan = OneStateScan->Next;
  972.             }
  973.  
  974.         return !OscillatorsRunning;
  975.     }
  976.